package com.wm.blog_admin.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wm.blog_admin.dao.TAdminDAO;
import com.wm.blog_admin.dao.TButtonPermissionDAO;
import com.wm.blog_admin.dao.TRoleDAO;
import com.wm.blog_admin.domain.TButtonPermissionDO;
import com.wm.blog_admin.query.TButtonPermissionQuery;
import com.wm.blog_common.base.BeanUtils;
import com.wm.blog_common.bean.QueryPage;
import com.wm.blog_common.constatnt.ErrorConstant;
import com.wm.blog_common.entity.TAdmin;
import com.wm.blog_common.entity.TButtonPermission;
import com.wm.blog_common.entity.TRole;
import com.wm.blog_common.enums.DeleteFlag;
import com.wm.blog_common.exception.BusinessException;
import com.wm.blog_common.result.Result;
import com.wm.blog_common.util.CommonUtil;
import com.wm.blog_common.util.DateUtil;
import com.wm.blog_common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jcajce.provider.symmetric.Noekeon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * <p>
 * 按钮权限表 服务实现类
 * </p>
 *
 * @author wm_yu
 * @since 2020-05-28
 */
@Service
@Slf4j
public class TButtonPermissionService{
    @Autowired
    private TButtonPermissionDAO tButtonPermissionDAO;

    @Autowired
    private TAdminDAO tAdminDAO;

    @Autowired
    private TRoleDAO tRoleDAO;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /**
     * 根据ID查询
     * @param id
     * @return
     */
    public Result<TButtonPermissionDO> selectById(Long id){
        Optional.ofNullable(id).orElseThrow(() -> new BusinessException(ErrorConstant.BUTTON_ID_EMPTY));
        return Result.success(BeanUtils.copyProperties(tButtonPermissionDAO.getById(id),TButtonPermissionDO.class));
    }

    /**
    * 根据ID删除
    * @return
    */
    public Result delete(TButtonPermissionQuery query){
        if(-1 == query.getAdminId()){
            return  Result.failure(ErrorConstant.USER_NO_LOGIN);
        }
        Optional.ofNullable(query.getId()).orElseThrow(() -> new BusinessException(ErrorConstant.BUTTON_ID_EMPTY));
        return tButtonPermissionDAO.removeById(query.getId())?Result.success():Result.failure();
    }

    /**
    * 添加
    * @param tButtonPermission
    * @return
    */
    public Result insert(TButtonPermission tButtonPermission){
        return tButtonPermissionDAO.save(tButtonPermission)?Result.success():Result.failure();
    }

    /**
    * 修改
    * @param tButtonPermission
    * @return
    */
    public Result update(TButtonPermission tButtonPermission){
        return tButtonPermissionDAO.updateById(tButtonPermission)?Result.success():Result.failure();
    }

    /**
    * 统计总数
    *
    * @param query
    * @return
    */
    public Result<Integer> count(TButtonPermissionQuery query) {
        return Result.success(tButtonPermissionDAO.count(this.combineQuery(query)));
    }

    /**
    * 列表查询
    * @param query
    * @return
    */
    public Result<List<TButtonPermissionDO>> list(TButtonPermissionQuery query){
        return Result.success(BeanUtils.copyListProperties(tButtonPermissionDAO.list(this.combineQuery(query)),TButtonPermissionDO.class));
    }
    /**
    * 分页查询
    * @param page
    * @return
    */
    public Result<Page<TButtonPermissionDO>> page(QueryPage page, TButtonPermissionQuery query){
        Page<TButtonPermissionDO> pageResult = tButtonPermissionDAO.pageList(page,query);
        //处理角色
        if(!ObjectUtils.isEmpty(pageResult) && !CollectionUtils.isEmpty(pageResult.getRecords())){
            List<TButtonPermissionDO> doList = pageResult.getRecords();
            List<Long> roleIdList = new ArrayList<>();
            //角色id
            doList.stream().filter(org.apache.commons.lang3.ObjectUtils::isNotEmpty).forEach(item -> {
                if(StringUtil.isNotEmpty(item.getRoleId())){
                    String[] split = item.getRoleId().split(",");
                    roleIdList.addAll(Arrays.stream(split).map(Long::parseLong).collect(Collectors.toList()));
                }
            });
            Map<Long, String> map = Optional
                    .ofNullable(tRoleDAO.listByIds(roleIdList))
                    .orElse(Collections.emptyList())
                    .stream()
                    .collect(Collectors.toMap(TRole::getId, TRole::getRoleName));

            doList.forEach(item -> {
                if(StringUtil.isNotEmpty(item.getRoleId())){
                    List<Long> list = Arrays.stream(item.getRoleId().split(",")).map(Long::parseLong).collect(Collectors.toList());
                    StringBuilder builder = new StringBuilder();
                    list.forEach(v -> {
                         builder.append(map.getOrDefault(v,"")).append(",");
                    });
                    item.setRoleName(builder.toString());
                }
            });
        }
         return Result.success(pageResult);
    }

    /**
    * 组装查询条件
    *
    * @param query
    * @return
    */
    private QueryWrapper<TButtonPermission> combineQuery(TButtonPermissionQuery query) {
        QueryWrapper<TButtonPermission> wrapper = new QueryWrapper<>();
        Optional.ofNullable(query).ifPresent(item -> {
            Optional.ofNullable(query.getUrl()).filter(StringUtil::isNotEmpty).ifPresent(x -> {
                wrapper.eq("url",query.getUrl());
            });
            Optional.ofNullable(query.getStatus()).ifPresent(x -> {
                wrapper.eq("status",x);
            });
            Optional.ofNullable(query.getMenuId()).ifPresent(x -> {
                wrapper.eq("menu_id",x);
            });
            Optional.ofNullable(query.getRoleId()).ifPresent(x -> {
                wrapper.apply(String.format("find_in_set(%s,role_id)",x));
            });
        });
        return wrapper;
    }

    public Result changeButton(Integer type,Long id, Long adminId) {
        if(ObjectUtils.isEmpty(type) || (!DeleteFlag.ENABLE.getValue().equals(type) && !DeleteFlag.DISABLE.getValue().equals(type))){
            return Result.failure(ErrorConstant.BUTTON_FLAG_MISS);
        }
        Optional.ofNullable(id).orElseThrow(() -> new BusinessException(ErrorConstant.BUTTON_ID_EMPTY));
        TAdmin admin = Optional.ofNullable(tAdminDAO.getById(adminId)).orElse(new TAdmin());
        TButtonPermission permission = new TButtonPermission();
        permission.setId(id);
        permission.setUpdateTime(DateUtil.getCurrentDate());
        permission.setStatus(type);
        permission.setCreator(admin.getUserName());
        return tButtonPermissionDAO.updateById(permission) ? Result.success():Result.failure();
    }

    /**
     * 新增/修改按钮权限
     * @param query
     * @return
     */
    public Result saveOrUpdate(TButtonPermissionQuery query) {
        if(StringUtil.isEmpty(query.getUrl())){
            return Result.failure(ErrorConstant.BUTTON_URL_EMPTY);
        }
        if(ObjectUtils.isEmpty(query.getMenuId()) || 0 == query.getMenuId()){
            return Result.failure(ErrorConstant.MENU_ID_EMPTY);
        }
        //校验非法字符
        String url = query.getUrl();
        if(!CommonUtil.checkButtonUrl(url)){
            return Result.failure(ErrorConstant.BUTTON_URL_ILLEGAL);
        }
        if(url.startsWith("/")){
            StringBuilder builder = new StringBuilder(url);
            url = builder.replace(0,1,"").toString();
        }
        TButtonPermission permission = new TButtonPermission();
        BeanUtils.copyProperties(query,permission);
        permission.setUrl(url);
        Date now = DateUtil.getCurrentDate();
        permission.setUpdateTime(now);
        TAdmin admin = Optional.ofNullable(tAdminDAO.getById(query.getAdminId())).orElse(new TAdmin());
        permission.setEditor(admin.getUserName());

        if(ObjectUtils.isEmpty(query.getId())){
            //新增
            permission.setCreateTime(now);
            //给定初始值
            permission.setRoleId("0,");
            //校验是否重名
            if(checkNameRepeat(query.getUrl())){
                return Result.failure(ErrorConstant.BUTTON_URL_REPEAT);
            }
            //追加sort
            TButtonPermissionQuery permissionQuery = new TButtonPermissionQuery();
            QueryWrapper<TButtonPermission> wrapper = this.combineQuery(permissionQuery);
            wrapper.last("order by sort desc limit 1");
            TButtonPermission buttonPermission = Optional.ofNullable(tButtonPermissionDAO.getOne(wrapper)).orElse(new TButtonPermission());
            permission.setStatus(DeleteFlag.DISABLE.getValue());
            permission.setSort(ObjectUtils.isEmpty(buttonPermission.getSort()) ? 0:buttonPermission.getSort() + 1);
            permission.setCreator(admin.getUserName());
        }
        return tButtonPermissionDAO.saveOrUpdate(permission) ? Result.success():Result.failure();
        }


        private boolean checkNameRepeat(String url){
            if(StringUtil.isEmpty(url)){
                return false;
            }
            TButtonPermissionQuery query = new TButtonPermissionQuery();
            query.setUrl(url);
            QueryWrapper<TButtonPermission> wrapper = this.combineQuery(query);
            int count = tButtonPermissionDAO.count(wrapper);
            return count > 0;
        }

    /**
     * 查询按钮权限
     * @param query
     * @return
     */
    public Result buttonList(TButtonPermissionQuery query) {
        query.setStatus(DeleteFlag.ENABLE.getValue());
        QueryWrapper<TButtonPermission> wrapper = this.combineQuery(query);
        List<TButtonPermission> list = Optional.ofNullable(tButtonPermissionDAO.list(wrapper)).orElse(Collections.emptyList());
        return Result.success(list);
    }

    /**
     * 角色设置按钮权限
     * @param query
     * @return
     */
    public Result setButton(TButtonPermissionQuery query) {
        Optional.ofNullable(query.getRoleId()).orElseThrow(() -> new BusinessException(ErrorConstant.ROLE_ID_EMPTY));
        //过滤重复id
        List<Long> idList = query.getIdList()
                .stream()
                .distinct()
                .collect(Collectors.toList());


        /**
         * 1.查询出之前属于该角色的所有的按钮权限,移除掉该角色的id
         *
         * 2.再在前端穿过来的全部重新加入该角色id进去
         *
         */
        TAdmin admin = Optional.ofNullable(tAdminDAO.getById(query.getAdminId())).orElse(new TAdmin());
        Date now = DateUtil.getCurrentDate();
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            QueryWrapper<TButtonPermission> wrapper = new QueryWrapper<>();
            wrapper.apply(String.format("find_in_set(%s,role_id)", query.getRoleId()));
            List<TButtonPermission> list = Optional.ofNullable(tButtonPermissionDAO.list(wrapper)).orElse(Collections.emptyList());
            if (!CollectionUtils.isEmpty(list)) {
                List<TButtonPermission> buttonPermissionList = list.stream().peek(item -> {
                    item.setRoleId(item.getRoleId().replaceAll(query.getRoleId() + ",", ""));
                    item.setUpdateTime(now);
                    item.setEditor(admin.getUserName());
                }).collect(Collectors.toList());
                //更新操作
                return tButtonPermissionDAO.updateBatchById(buttonPermissionList);
            }
            return true;
        }, threadPoolTaskExecutor).thenAccept(item -> {
            if (item && !CollectionUtils.isEmpty(idList)) {
                //执行重新绑定操作
                List<TButtonPermission> list = idList.stream().map(x -> {
                    TButtonPermission buttonPermission = new TButtonPermission();
                    buttonPermission.setUpdateTime(now);
                    buttonPermission.setId(x);
                    buttonPermission.setEditor(admin.getUserName());
                    //默认是0,
                    String oldRoleId = StringUtil.isEmpty(buttonPermission.getRoleId()) ? "0,":buttonPermission.getRoleId();
                    buttonPermission.setRoleId(oldRoleId + query.getRoleId() + ",");
                    return buttonPermission;
                }).collect(Collectors.toList());
                boolean b = tButtonPermissionDAO.updateBatchById(list);
                log.info("角色设置按钮权限:{}", b);
            }
        });
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
           log.error("执行异常:{}",e.getMessage(),e);
           return Result.failure();
        }
        return Result.success();
    }
}







